/*
 * Copyright (c) 2024 iSoftStone Education Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include "los_task.h"
#include "ohos_init.h"
#include "iot_errno.h"
#include "iot_gpio.h"
#include "sht30.h"

/* 人体感应传感器GPIO */
#define GPIO_BODY_INDUCTION      GPIO0_PA3
#define GPIO_LED               GPIO0_PA5

/* 全局状态标志 */
static volatile uint8_t g_human_detected = 0;  // 人体检测标志
static volatile uint8_t g_led_state = 0;       // LED当前状态

/***************************************************************
* 函数名称: gpio_isr_func
* 说    明: gpio中断响应处理函数
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void gpio_isr_func(void *args)
{
    // 检测到人体
    g_human_detected = 1;
    printf("Human detected!\n");
    
    // 立即点亮LED
    IoTGpioSetOutputVal(GPIO_LED, IOT_GPIO_VALUE1);
    g_led_state = 1;
}

/***************************************************************
* 函数名称: led_blink_task
* 说    明: LED控制任务
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void led_blink_task()
{
    unsigned int last_detection_time = 0;
    const unsigned int detection_timeout = 2000; // 2秒无人体活动后恢复闪烁
    
    while (1) {
        if (g_human_detected) {
            // 人体存在，保持LED点亮
            last_detection_time = LOS_TickCountGet();
            
            // 检查是否人体已经离开
            uint16_t val;
            IoTGpioGetInputVal(GPIO_BODY_INDUCTION, &val);
            if (val == IOT_GPIO_VALUE0) {
                g_human_detected = 0;
                printf("Human left.\n");
            }
        } else {
            // 人体不存在，检查是否超时
            if (LOS_TickCountGet() - last_detection_time > detection_timeout) {
                // 正常闪烁模式
                g_led_state = !g_led_state;
                IoTGpioSetOutputVal(GPIO_LED, g_led_state);
            }
        }
        
        LOS_Msleep(g_human_detected ? 100 : 500);
    }
}

/***************************************************************
* 函数名称: sht30_monitor_task
* 说    明: 温湿度监测任务
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void sht30_monitor_task()
{
    double temp_hum[2] = {0};
    
    // 初始化SHT30传感器
    sht30_init();
    
    while (1) {
        // 读取温湿度数据
        sht30_read_data(temp_hum);
        
        // 输出温湿度值
        printf("Temperature: %.1f°C, Humidity: %.1f%%\n", temp_hum[0], temp_hum[1]);
        
        // 每5秒读取一次
        LOS_Msleep(5000);
    }
}

/***************************************************************
* 函数名称: gpio_interrupt_example
* 说    明: 主初始化函数
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void gpio_interrupt_example()
{
    unsigned int ret;
    unsigned int led_task_id, sensor_task_id, sht30_task_id;
    TSK_INIT_PARAM_S led_task = {0};
    TSK_INIT_PARAM_S sensor_task = {0};
    TSK_INIT_PARAM_S sht30_task = {0};

    // 初始化LED GPIO
    IoTGpioInit(GPIO_LED);
    IoTGpioSetDir(GPIO_LED, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(GPIO_LED, IOT_GPIO_VALUE0);

    // 初始化人体感应传感器GPIO
    IoTGpioInit(GPIO_BODY_INDUCTION);
    IoTGpioSetDir(GPIO_BODY_INDUCTION, IOT_GPIO_DIR_IN);
    
    // 设置中断（上升沿触发）
    ret = IoTGpioRegisterIsrFunc(GPIO_BODY_INDUCTION, 
        IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_RISE_LEVEL_HIGH, gpio_isr_func, NULL);
    if (ret != IOT_SUCCESS) {
        printf("Failed to register ISR: %d\n", ret);
        return;
    }
    IoTGpioSetIsrMask(GPIO_BODY_INDUCTION, FALSE);

    // 创建LED控制任务
    led_task.pfnTaskEntry = (TSK_ENTRY_FUNC)led_blink_task;
    led_task.uwStackSize = 2048;
    led_task.pcName = "LED Task";
    led_task.usTaskPrio = 25;
    ret = LOS_TaskCreate(&led_task_id, &led_task);
    if (ret != LOS_OK) {
        printf("Failed to create LED task: 0x%x\n", ret);
    }

    // 创建温湿度监测任务
    sht30_task.pfnTaskEntry = (TSK_ENTRY_FUNC)sht30_monitor_task;
    sht30_task.uwStackSize = 2048;
    sht30_task.pcName = "SHT30 Task";
    sht30_task.usTaskPrio = 24;  // 优先级略低于LED任务
    ret = LOS_TaskCreate(&sht30_task_id, &sht30_task);
    if (ret != LOS_OK) {
        printf("Failed to create SHT30 task: 0x%x\n", ret);
    }

    printf("System started: Human detection, LED control and SHT30 monitoring.\n");
}

APP_FEATURE_INIT(gpio_interrupt_example);
